#include "Channel.hpp"
namespace mq
{
    class Connection
    {
    public:
        using ConnectionPtr = shared_ptr<Connection>;
        Connection(const VirtualHost::VirtualHostPtr &host, const ConsumerManager::ConsumerManagerPtr &cmp,
                   const ProtobufCodecPtr &codec, const muduo::net::TcpConnectionPtr &conn,
                   const ThreadPool::ThreadPoolPtr &pool)
            : _host(host), _cmp(cmp), _codec(codec), _conn(conn), _pool(pool), _channels(make_shared<mq::ChannelManager>())
        {
        }

        void openChannel(const openChannelRequestPtr &req)
        {
            bool ret = _channels->openChannel(req->cid(), _host, _cmp, _codec, _conn, _pool);
            if (ret == false)
            {
                DLOG("信道已存在: %s", req->cid().c_str());
                return;
            }
            return basicResponse(true, req->rid(), req->cid());
        }

        void closeChannel(const closeChannelRequestPtr &req)
        {
            _channels->closeChannel(req->cid());
            return basicResponse(true, req->rid(), req->cid());
        }
        Channel::ChannelPtr getChannel(const string &cid)
        {
            return _channels->getChannel(cid);
        }

    private:
        void basicResponse(bool ok, const string &rid, const string &cid)
        {
            basicCommonResponse resp;
            resp.set_ok(ok);
            resp.set_rid(rid);
            resp.set_cid(cid);
            _codec->send(_conn, resp);
        }

    private:
        muduo::net::TcpConnectionPtr _conn;
        ProtobufCodecPtr _codec;
        ConsumerManager::ConsumerManagerPtr _cmp;
        VirtualHost::VirtualHostPtr _host;
        ThreadPool::ThreadPoolPtr _pool;
        ChannelManager::ChannelManagerPtr _channels;
    };
    class ConnectionManager
    {
    public:
        using ConnectionManagerPtr = shared_ptr<ConnectionManager>;
        ConnectionManager()
        {
        }
        void newConnection(const VirtualHost::VirtualHostPtr &host, const ConsumerManager::ConsumerManagerPtr &cmp,
                           const ProtobufCodecPtr &codec, const muduo::net::TcpConnectionPtr &conn,
                           const ThreadPool::ThreadPoolPtr &pool)
        {
            unique_lock<mutex> lock(_mutex);
            auto it = _conns.find(conn);
            if (it != _conns.end())
            {
                DLOG("连接已存在:%p", conn.get());
                return;
            }
            Connection::ConnectionPtr cp = make_shared<Connection>(host, cmp, codec, conn, pool);
            _conns.insert(make_pair(conn, cp));
        }
        void delConnection(const muduo::net::TcpConnectionPtr &conn)
        {
            unique_lock<mutex> lock(_mutex);
            auto it = _conns.find(conn);
            if (it == _conns.end())
            {
                return;
            }
            _conns.erase(conn);
        }
        Connection::ConnectionPtr getConnection(const muduo::net::TcpConnectionPtr &conn)
        {
            unique_lock<mutex> lock(_mutex);
            auto it = _conns.find(conn);
            if (it == _conns.end())
            {

                DLOG("目标连接不存在:%p", conn.get());
                return Connection::ConnectionPtr();
            }
            return it->second;
        }

    private:
        mutex _mutex;
        unordered_map<muduo::net::TcpConnectionPtr, Connection::ConnectionPtr> _conns;
    };
}